from google.appengine.ext import db

import timeformat
import logging
import datetime
import traceback

class UserObject(db.Model):
  user = db.UserProperty()
  create_date = db.DateTimeProperty(auto_now_add=True)
  
  
class ConfigSetting(UserObject):
  setting_key = db.StringProperty()
  value = db.StringProperty()
  description = db.StringProperty()
  
  
class ActionCategory(UserObject):
  name = db.StringProperty()
  description = db.StringProperty()

  
class SomedayMaybeIdea(UserObject):
  idea = db.StringProperty()
  url = db.LinkProperty()
  label = db.StringProperty()
  modified_date = db.DateTimeProperty()
  

class Project(UserObject):
  description = db.StringProperty()
  project_type = db.StringProperty()
  tasks = db.ListProperty(db.Key)
  is_complete = db.BooleanProperty()
  
  def delete_everything(self):
    self.delete_tasks()
    self.delete()
  
  def delete_tasks(self):
    for key in self.tasks:
      task = Task.get(key)
      if task:
        task.delete()
    self.tasks = []
    self.put()
  
  @staticmethod
  def compare_by_due(x, y):
    if not x or not x.due_date:
      return -1
    if not y or not y.due_date:
      return +1
    if x.due_date < y.due_date:
      return -1
    if x.due_date > y.due_date:
      return +1
    return 0
  
  def subtasks(self):
    try:
      task_list = []
      if self.tasks:
        task_list = Task.get(self.tasks)
        task_list.sort(Project.compare_by_due)
      return task_list
    except:
      logging.error(traceback.format_exc())
      return None
      
  def key_description_string(self):
    return str(self.key()) + '|' + self.description
      
  def as_json(self):
    return {
      "project": self.key_description_string(),
      "type": self.project_type,
      "has_tasks": str(self.has_subtasks())}
      
  def has_subtasks(self):
    return len(self.tasks) > 0
    
  def uncomplete(self):
    self.is_complete = False
    self.put()
    
  def complete(self):
    self.is_complete = True
    self.put()
  
  
class Task(UserObject):
  action = db.StringProperty()
  has_due_date = db.BooleanProperty()
  due_date = db.DateTimeProperty()
  is_complete = db.BooleanProperty()
  complete_date = db.DateTimeProperty()
  parent_project = db.ReferenceProperty(Project)
  
  def parent(self):
    return self.parent_project.key_description_string()
      
  def complete(self):
    self.is_complete = True
    self.complete_date = datetime.datetime.now()
    self.put()
          
  def key_action_string(self):
    return str(self.key()) + '|' + self.action
  
  def date_string(self, date):
    return timeformat.format('%m[NP]/%d[NP]/%Y', date.timetuple()) if date else ''
    
  def due_date_string(self):
    return self.date_string(self.due_date) if self.has_due_date else ''
    
  def complete_date_string(self):
    return self.date_string(self.complete_date)
    
  def due_date_json(self):
    if self.has_due_date:
      return 'Date(%s)' % timeformat.format('%m/%d/%Y', self.due_date.timetuple()) 
    else:
      return ''
        
  def as_json(self):
    return {
      "task": self.key_action_string(),
      "due": self.due_date_json(),
      "due_year": self.due_date.year if self.due_date else -1,
      "due_month": self.due_date.month if self.due_date else -1,
      "due_day": self.due_date.day if self.due_date else -1,
      "is_complete": str(self.is_complete)}
  
  
class NextAction(Task):
  category = db.ReferenceProperty(ActionCategory)
  phone_number = db.PhoneNumberProperty()
  url = db.LinkProperty()
  tag = db.StringProperty()
  
  def extra_info(self):
    return self.phone_number or self.url or ''
      
  def category_string(self):
    return self.category.name if self.category else ''
      
  def as_json(self):
    return {
      "action": self.key_action_string(),
      "category": self.category_string(),
      "extra": self.extra_info(),
      "tag": self.tag,
      "due": self.due_date_json(),
      "phone": self.phone_number or '',
      "url": self.url or '',
      "due_year": self.due_date.year if self.due_date else -1,
      "due_month": self.due_date.month if self.due_date else -1,
      "due_day": self.due_date.day if self.due_date else -1}

